import { BaseRenderer } from "./base_renderer.mjs";
import { thin } from "../../../thin3/thin3.mjs";

/**
 * 选择框渲染器
 * 处理静态选项和动态AJAX选项的渲染
 */
export class SelectRenderer extends BaseRenderer {
  /**
   * 创建选择框
   * @param {Object} schema - Schema定义
   * @param {*} data - 数据值
   * @param {Function} updateData - 数据更新函数
   * @returns {Promise<HTMLElement>} 选择框元素
   */
  static async createSelect(schema, data, updateData) {
    const select = document.createElement("select");
    select.name = schema.path || schema.name; // 添加name属性

    if (schema.thin.ajax) {
      await this.loadAjaxOptions(select, schema);
    } else if (schema.thin.options) {
      this.loadStaticOptions(select, schema);
    }

    select.value = data || "";
    select.onchange = (e) => updateData(e.target.value);
    return select;
  }

  /**
   * 加载AJAX选项
   * @param {HTMLSelectElement} select - 选择框元素
   * @param {Object} schema - Schema定义
   */
  static async loadAjaxOptions(select, schema) {
    const ajax = schema.thin.ajax;

    // 添加watch支持
    if (ajax.watch) {
      const watched = select.closest("form")?.querySelector(ajax.watch);
      if (watched) {
        watched.addEventListener("change", () => {
          this.reloadOptions(select, schema);
        });
      }
    }

    await this.reloadOptions(select, schema);
  }

  /**
   * 重新加载选项
   * @param {HTMLSelectElement} select - 选择框元素
   * @param {Object} schema - Schema定义
   */
  static async reloadOptions(select, schema) {
    const ajax = schema.thin.ajax;
    try {
      const response = await new Promise((resolve, reject) => {
        thin.ajax({
          url: ajax.url,
          type: ajax.method || "post",
          contentType: "application/JSON",
          data: ajax.data || {},
          success: resolve,
          error: reject,
        });
      });

      let options = response;
      if (ajax.datapath) {
        ajax.datapath.split(".").forEach((path) => {
          options = options[path];
        });
      }

      // 清空现有选项
      select.innerHTML = "";
      this.addOptions(select, options, ajax);
    } catch (error) {
      console.error("Failed to load select options:", error);
    }
  }

  /**
   * 加载静态选项
   * @param {HTMLSelectElement} select - 选择框元素
   * @param {Object} schema - Schema定义
   */
  static loadStaticOptions(select, schema) {
    const options = schema.thin.options || [];
    this.addEmptyOption(select, schema);

    options.forEach((option) => {
      const optionEl = document.createElement("option");
      if (typeof option === "object") {
        optionEl.value = option.value;
        optionEl.textContent = option.label || option.value;
      } else {
        optionEl.value = option;
        optionEl.textContent = option;
      }
      select.appendChild(optionEl);
    });
  }

  /**
   * 添加空选项
   * @param {HTMLSelectElement} select - 选择框元素
   * @param {Object} schema - Schema定义
   */
  static addEmptyOption(select, schema) {
    // 优先使用thin.required
    const isRequired =
      schema.thin?.required !== undefined
        ? schema.thin.required
        : schema.parent &&
          schema.parent.required &&
          schema.parent.required.includes(schema.name);
    if (!isRequired) {
      const emptyOption = document.createElement("option");
      emptyOption.value = "";
      emptyOption.textContent = "-- 请选择 --";
      select.appendChild(emptyOption);
    }
  }

  /**
   * 添加选项
   * @param {HTMLSelectElement} select - 选择框元素
   * @param {Array} options - 选项数据
   * @param {Object} ajax - AJAX配置
   */
  static addOptions(select, options, ajax) {
    // 添加空选项
    select.options.add(new Option(""));

    if (!Array.isArray(options)) return;

    options.forEach((option) => {
      let value, text;

      // 处理选项的值：支持模板语法[[xxx]]或直接取值
      if (ajax.value) {
        value = /\[\[[\w/.]+\]\]/.test(ajax.value)
          ? this.processTemplate(ajax.value, option)
          : option[ajax.value];
      }

      // 处理选项的显示文本
      if (ajax.text) {
        text = this.processTemplate(ajax.text || ajax.value, option);
      } else {
        text = value;
      }

      const opt = new Option(text, value);
      opt.thin_data = option; // 在选项上存储原始数据，供后续使用
      select.options.add(opt);
    });
  }

  /**
   * 处理模板
   * @param {string} template - 模板字符串
   * @param {Object} data - 数据对象
   * @returns {string} 处理后的字符串
   */
  static processTemplate(template, data) {
    if (!template) return "";
    return template.replace(/\[\[(.*?)\]\]/g, (match, key) => {
      return data[key] || "";
    });
  }
}
